home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1995 February: Tool Chest / Dev.CD Feb 95 / Dev.CD Feb 95.toast / Tool Chest / Development Tools & Languages / Dylan Related / Mindy-1.1 (sources only) / mindy-1.1 / interp / nlx.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-28  |  7.8 KB  |  294 lines  |  [TEXT/ttxt]

  1. /**********************************************************************\
  2. *
  3. *  Copyright (c) 1994  Carnegie Mellon University
  4. *  All rights reserved.
  5. *  
  6. *  Use and copying of this software and preparation of derivative
  7. *  works based on this software are permitted, including commercial
  8. *  use, provided that the following conditions are observed:
  9. *  
  10. *  1. This copyright notice must be retained in full on any copies
  11. *     and on appropriate parts of any derivative works.
  12. *  2. Documentation (paper or online) accompanying any system that
  13. *     incorporates this software, or any part of it, must acknowledge
  14. *     the contribution of the Gwydion Project at Carnegie Mellon
  15. *     University.
  16. *  
  17. *  This software is made available "as is".  Neither the authors nor
  18. *  Carnegie Mellon University make any warranty about the software,
  19. *  its performance, or its conformity to any specification.
  20. *  
  21. *  Bug reports, questions, comments, and suggestions should be sent by
  22. *  E-mail to the Internet address "gwydion-bugs@cs.cmu.edu".
  23. *
  24. ***********************************************************************
  25. *
  26. * $Header: nlx.c,v 1.6 94/06/27 16:32:21 wlott Exp $
  27. *
  28. * This file implements non-local exit.
  29. *
  30. \**********************************************************************/
  31.  
  32. #include "mindy.h"
  33. #include "gc.h"
  34. #include "thread.h"
  35. #include "func.h"
  36. #include "list.h"
  37. #include "bool.h"
  38. #include "obj.h"
  39. #include "sym.h"
  40. #include "class.h"
  41. #include "error.h"
  42. #include "def.h"
  43.  
  44. static obj_t obj_CatchBlockClass = 0;
  45.  
  46.  
  47. /* Unwind-protect. */
  48.  
  49. struct uwp {
  50.     obj_t prev_uwp;
  51.     obj_t handlers;
  52.     obj_t cleanup;
  53. };
  54.  
  55. static void done_with_cleanup(struct thread *thread, obj_t *cleanup_vals)
  56. {
  57.     obj_t *old_sp, *vals;
  58.  
  59.     /* Get the pointer to the values from the protected form from the stack.
  60.        We pushed it just before calling the cleanup, so it just below the
  61.        cleanup values. */
  62.     vals = obj_rawptr(cleanup_vals[-1]);
  63.  
  64.     /* Reset the stack to just after the protected form values. */
  65.     thread->sp = cleanup_vals - 1;
  66.  
  67.     /* Return those values. */
  68.     old_sp = pop_linkage(thread);
  69.     do_return(thread, old_sp, vals);
  70. }
  71.  
  72. static void do_uwp_cleanup(struct thread *thread, obj_t *vals)
  73. {
  74.     struct uwp *cur_uwp = thread->cur_uwp;
  75.  
  76.     /* Unlink the unwind protect */
  77.     thread->cur_uwp = obj_rawptr(cur_uwp->prev_uwp);
  78.  
  79.     /* push a pointer to the values. */
  80.     *thread->sp++ = rawptr_obj(vals);
  81.  
  82.     /* call the cleanup function. */
  83.     *thread->sp++ = cur_uwp->cleanup;
  84.     set_c_continuation(thread, done_with_cleanup);
  85.     invoke(thread, 0);
  86. }
  87.  
  88. static void uwp(struct thread *thread, int nargs)
  89. {
  90.     obj_t *args, *fp;
  91.     struct uwp *cur_uwp;
  92.  
  93.     assert(nargs == 2);
  94.  
  95.     args = thread->sp - 2;
  96.     fp = push_linkage(thread, args);
  97.     cur_uwp = (struct uwp *)fp;
  98.  
  99.     /* link in the new unwind protect */
  100.     thread->sp = fp + sizeof(struct uwp)/sizeof(obj_t);
  101.     cur_uwp->prev_uwp = rawptr_obj(thread->cur_uwp);
  102.     thread->cur_uwp = cur_uwp;
  103.     cur_uwp->handlers = thread->handlers;
  104.     cur_uwp->cleanup = args[1];
  105.  
  106.     /* call the protected form. */
  107.     *thread->sp++ = args[0];
  108.     set_c_continuation(thread, do_uwp_cleanup);
  109.     invoke(thread, 0);
  110. }
  111.  
  112.  
  113. /* Catch */
  114.  
  115. struct catch_block {
  116.     obj_t class;
  117.     struct thread *thread;
  118.     struct uwp *cur_uwp;
  119.     obj_t prev_catch;
  120.     obj_t *fp;
  121.     obj_t handlers;
  122. };
  123.  
  124. static void unlink_catch(struct thread *thread, obj_t *vals)
  125. {
  126.     obj_t catch_block;
  127.     obj_t *old_sp;
  128.  
  129.     /* Unlink and invalidate the current catch block. */
  130.     catch_block = thread->cur_catch;
  131.     thread->cur_catch = obj_ptr(struct catch_block *, catch_block)->prev_catch;
  132.     obj_ptr(struct catch_block *, catch_block)->thread = NULL;
  133.     obj_ptr(struct catch_block *, catch_block)->prev_catch = obj_False;
  134.  
  135.     /* Return the same values we got. */
  136.     old_sp = pop_linkage(thread);
  137.     do_return(thread, old_sp, vals);
  138. }
  139.  
  140. static void catch(struct thread *thread, int nargs)
  141. {
  142.     obj_t *args, *fp;
  143.     obj_t catch_block;
  144.  
  145.     assert(nargs == 1);
  146.  
  147.     args = thread->sp - 1;
  148.     fp = push_linkage(thread, args);
  149.  
  150.     catch_block = alloc(obj_CatchBlockClass, sizeof(struct catch_block));
  151.     obj_ptr(struct catch_block *, catch_block)->thread = thread;
  152.     obj_ptr(struct catch_block *, catch_block)->cur_uwp = thread->cur_uwp;
  153.     obj_ptr(struct catch_block *, catch_block)->prev_catch = thread->cur_catch;
  154.     obj_ptr(struct catch_block *, catch_block)->fp = fp;
  155.     obj_ptr(struct catch_block *, catch_block)->handlers = thread->handlers;
  156.     thread->cur_catch = catch_block;
  157.  
  158.     thread->sp = fp + 2;
  159.     fp[0] = args[0];
  160.     fp[1] = catch_block;
  161.     set_c_continuation(thread, unlink_catch);
  162.     invoke(thread, 1);
  163. }
  164.  
  165.  
  166. /* Throw */
  167.  
  168. static void unwind(struct thread *thread, obj_t catch_block, obj_t *vals);
  169.  
  170. static void throw(struct thread *thread, int nargs)
  171. {
  172.     obj_t *args;
  173.     obj_t catch_block;
  174.  
  175.     assert (nargs > 0);
  176.  
  177.     args = thread->sp - nargs;
  178.     catch_block = args[0];
  179.     if (obj_ptr(struct catch_block *, catch_block)->thread != thread) {
  180.     push_linkage(thread, args);
  181.     error("Bogus throw");
  182.     }
  183.  
  184.     unwind(thread, args[0], args+1);
  185. }
  186.  
  187. static void continue_unwind(struct thread *thread, obj_t *cleanup_vals)
  188. {
  189.     obj_t catch_block = cleanup_vals[-1];
  190.     obj_t *vals = thread->fp;
  191.  
  192.     thread->sp = cleanup_vals - 1;
  193.  
  194.     unwind(thread, catch_block, vals);
  195. }
  196.  
  197. static void unwind(struct thread *thread, obj_t catch_block, obj_t *vals)
  198. {
  199.     struct uwp *cur_uwp;
  200.     obj_t cur_catch;
  201.  
  202.     cur_uwp = thread->cur_uwp;
  203.  
  204.     do {
  205.     cur_catch = thread->cur_catch;
  206.     if (cur_uwp != obj_ptr(struct catch_block *, cur_catch)->cur_uwp) {
  207.         obj_t cleanup = cur_uwp->cleanup;
  208.         obj_t *dst = (obj_t *)cur_uwp;
  209.         obj_t *src = vals;
  210.         obj_t *end = thread->sp;
  211.  
  212.         /* Set the frame pointer to where the values will show up. */
  213.         thread->fp = dst;
  214.  
  215.         /* Restore the handlers, and unlink the uwp. */
  216.         thread->handlers = cur_uwp->handlers;
  217.         thread->cur_uwp = obj_rawptr(cur_uwp->prev_uwp);
  218.  
  219.         /* Copy the values down the stack, and save the catch block */
  220.         while (src < end)
  221.         *dst++ = *src++;
  222.         thread->sp = dst+2;
  223.         dst[0] = catch_block;
  224.  
  225.         /* call the cleanup function. */
  226.         dst[1] = cleanup;
  227.         set_c_continuation(thread, continue_unwind);
  228.         invoke(thread, 0);
  229.         return;
  230.     }
  231.     /* Unlink the catch block we just unwound past. */
  232.     obj_ptr(struct catch_block *, cur_catch)->thread = NULL;
  233.     thread->handlers = obj_ptr(struct catch_block *, cur_catch)->handlers;
  234.     thread->cur_catch=obj_ptr(struct catch_block *, cur_catch)->prev_catch;
  235.     } while (cur_catch != catch_block);
  236.  
  237.     /* Restore the frame pointer and the handlers. */
  238.     thread->fp = obj_ptr(struct catch_block *, cur_catch)->fp;
  239.     thread->handlers = obj_ptr(struct catch_block *, cur_catch)->handlers;
  240.  
  241.     /* And back we go. */
  242.     do_return(thread, pop_linkage(thread), vals);
  243. }
  244.  
  245.  
  246. /* GC stuff. */
  247.  
  248. static int scav_catch(struct object *o)
  249. {
  250.     struct catch_block *catch = (struct catch_block *)o;
  251.  
  252.     scavenge(&catch->prev_catch);
  253.     scavenge(&catch->handlers);
  254.  
  255.     return sizeof(struct catch_block);
  256. }
  257.  
  258. static obj_t trans_catch(obj_t catch)
  259. {
  260.     return transport(catch, sizeof(struct catch_block));
  261. }
  262.  
  263. void scavenge_nlx_roots(void)
  264. {
  265.     scavenge(&obj_CatchBlockClass);
  266. }
  267.  
  268.  
  269. /* Init stuff. */
  270.  
  271. void make_nlx_classes(void)
  272. {
  273.     obj_CatchBlockClass = make_builtin_class(scav_catch, trans_catch);
  274. }
  275.  
  276. void init_nlx_classes(void)
  277. {
  278.     init_builtin_class(obj_CatchBlockClass, "<catch>", obj_ObjectClass, NULL);
  279. }
  280.  
  281.  
  282. void init_nlx_functions(void)
  283. {
  284.     define_constant("uwp",
  285.             make_raw_function("uwp", 2, FALSE, obj_False, FALSE,
  286.                       obj_Nil, obj_ObjectClass, uwp));
  287.     define_constant("catch",
  288.             make_raw_function("catch", 1, FALSE, obj_False, FALSE,
  289.                       obj_Nil, obj_ObjectClass, catch));
  290.     define_constant("throw",
  291.             make_raw_function("throw", 1, TRUE, obj_False, FALSE,
  292.                       obj_Nil, obj_ObjectClass, throw));
  293. }
  294.